//***************************************************************
//  File:    GameObject.cpp
//  Date:    12/17/2012
//  Author:  liangxc (liangxc2010@gmail.com)
//-------------------------------------------------------------
//
//-------------------------------------------------------------
//  This file is part of Hare2D Game Engine.
//  Copyright (C) All Rights Reserved
//***************************************************************
//
//***************************************************************
#include "PCH.h"

#include "graphics/GameObject.h"
#include "GameObjectPage.h"

IMPLEMENT_ABSTRACT_CLASS(GameObjectPage, EditorPage)

	GameObjectPage::GameObjectPage(wxWindow* parent, SceneMIMEHandler* handler)
	:EditorPage(parent)
	,mime(handler)
	,isModified(false)
{
	canvas = new wxHareCanvas(this);
	scene = getHareApp()->createSceneManager();
	scene->setSceneListener(new SceneListenerEditorWrapper<GameObjectPage>(this));
	canvas->getRenderWindow()->setSceneManager(scene);


	wxBoxSizer* sizer = new wxBoxSizer(wxVERTICAL);
	sizer->Add(canvas, 1, wxEXPAND, 0);
	SetSizer(sizer);
	Layout();

	canvas->Connect(wxEVT_SIZE, wxSizeEventHandler(GameObjectPage::onSize), 0, this);
	canvas->Connect(wxEVT_LEFT_DOWN, wxMouseEventHandler(GameObjectPage::onLButtonDown), 0, this);
	canvas->Connect(wxEVT_LEFT_UP, wxMouseEventHandler(GameObjectPage::onLButtonUp), 0, this);
	canvas->Connect(wxEVT_MOTION, wxMouseEventHandler(GameObjectPage::onMouseMove), 0, this);
	canvas->Connect(wxEVT_RIGHT_DOWN, wxMouseEventHandler(GameObjectPage::onRButtonDown), 0, this);

	Connect(wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(GameObjectPage::onMenuSelected), 0, this);
}

GameObjectPage::~GameObjectPage()
{
	if (!Manager::isAppShuttingDown()){
		Manager::getInstancePtr()->getExplorerManager()->removeAllProperties();
	}
}

void GameObjectPage::updateTitle()
{
	String title = "[GameObjectEditor]";
	if (gameObj) title += gameObj->getUrl();

	if (isModified)
		setTitle(wxT("*") + wxString::FromUTF8(title.c_str()));
	else
		setTitle(wxString::FromUTF8(title.c_str()));
}

void GameObjectPage::setModified(bool modified)
{
	if (modified != isModified){
		isModified = modified;
		updateTitle();
	}
}

bool GameObjectPage::saveAs()
{
	bool ret = false;

	wxFileDialog* dlg = new wxFileDialog(Manager::getInstancePtr()->getAppWindow(),
		_T("Save GameObject resource as"),
		_T(""),
		_T(""),
		_T("ImageSprite Resource (*.gameobj)|*.gameobj|Any file (*)|*"),
		wxSAVE | wxOVERWRITE_PROMPT);

	if (dlg->ShowModal() == wxID_OK){
		static const char* tempFileName = "/editor/~gameobj.temp";
		FileSystem::getSingletonPtr()->remove(tempFileName);
		gameObj->saveToXml(tempFileName);
		String dir = FileSystem::getSingletonPtr()->getRealDir(tempFileName);
		dir += tempFileName;
		wxString tempFile = wxString::FromUTF8(dir.c_str());
		wxFileName fName(tempFile);
		if (fName.FileExists()){
			wxString fileName = dlg->GetPath();
			ret = wxCopyFile(fName.GetFullPath(), fileName);
		}
	}

	dlg->Destroy();
	return ret;
}

bool GameObjectPage::save()
{
	if (!gameObj)
		return true;

	bool ret = false;
	if (gameObj->getUrl().empty())
		ret = saveAs();
	else
		ret = gameObj->saveToXml(gameObj->getUrl());

	if (ret)
		setModified(false);

	return ret;
}

void GameObjectPage::renderScene()
{
	wxSize size = canvas->GetClientSize();
	if (size.GetWidth() > 0 && size.GetHeight() > 0){
		uint32 oldColor = getCanvas()->getColor();
		getCanvas()->setColor(0xff00ff00);
		getCanvas()->drawLine(-1000, size.GetHeight()/2, 1000, size.GetHeight()/2);
		getCanvas()->drawLine(size.GetWidth()/2, -1000, size.GetWidth()/2, 1000);
		getCanvas()->setColor(oldColor);
	}

}

void GameObjectPage::setGameObject(GameObject* obj)
{
	gameObj = obj;
	gameObj->setPosition(0,0);
	
	scene->addObject(scene->getRootObject(), gameObj);

	updateTitle();

	Manager::getInstancePtr()->getExplorerManager()->removeAllProperties();
	Manager::getInstancePtr()->getExplorerManager()->bindProperty(wxT("ImageSpriteProperity"), gameObj);
}

void GameObjectPage::onSize(wxSizeEvent& event)
{
	wxSize size = canvas->GetClientSize();
	if (size.GetWidth() > 0 && size.GetHeight() > 0){
		canvas->getRenderWindow()->resize(size.GetWidth(), size.GetHeight());
		canvas->getRenderWindow()->moveCameraTo(-size.GetWidth()/2, -size.GetHeight()/2);
	}
	event.Skip();
}

void GameObjectPage::onLButtonDown(wxMouseEvent& event)
{
	mousePos = event.GetPosition();
}

void GameObjectPage::onLButtonUp(wxMouseEvent& event)
{
	Manager::getInstancePtr()->getExplorerManager()->removeAllProperties();
	Manager::getInstancePtr()->getExplorerManager()->bindProperty(wxT("ImageSpriteProperity"), gameObj);
}

void GameObjectPage::onMouseMove(wxMouseEvent& event)
{
	if (!gameObj)
		return;

	if (event.Dragging() && event.LeftIsDown()){
		wxPoint offset = event.GetPosition() - mousePos;
		mousePos = event.GetPosition();
		gameObj->move(offset.x, offset.y);
		setModified(true);
	}
}

void GameObjectPage::onRButtonDown(wxMouseEvent& event)
{
	wxMenu* contexMenu = new wxMenu;
	contexMenu->Append(0, wxT("Add Component"));
	PopupMenu(contexMenu);

	delete contexMenu;

	event.Skip();
}

void GameObjectPage::onMenuSelected(wxCommandEvent& event)
{
	int id = event.GetId();

	switch (id)
	{
	case 0:
		gameObj->AddComponent();

		Manager::getInstancePtr()->getExplorerManager()->removeAllProperties();
		Manager::getInstancePtr()->getExplorerManager()->bindProperty(wxT("ImageSpriteProperity"), gameObj);
		break;
	}
}